// -*- c++ -*-

//
// StreamFlowC : A C++ coding style to describe hardware structure for stream processing
//

// Copyright (c) 2009 the handy-eda-utils developer(s).
// Distributed under the MIT License.
// (See accompanying file COPYING or copy at
//  http://www.opensource.org/licenses/mit-license.php.)

struct trig_t {};

} // namespace sfcut
namespace streamflowc {
template <> struct portref< ::sfcut::trig_t > : private portref_base {
  typedef ::sfcut::trig_t T;
  void operator=(port<T>& dst) { assign(&dst); }
  void operator=(portref<T>& src) { chain(&src); }
  void operator()(port<T>::arg_type x = T()) { (*static_cast<port<T>*>(get()))(x); }
};
} // namespace streamflowc
namespace sfcut {

template <typename T>
module trig {
 param:
  int     period;  // -N/+N : trigger before/after every N inputs
 input:
  T       a;
 output:
  T       y;
  trig_t  t;
};

struct trig {
  int  m_count;
  bool m_preceed;
};

trig() {
  m_count = 0;
  m_preceed = (m_period < 0);
  if (m_preceed)   m_period = - m_period;
}

trig(a) {
  if (m_preceed && m_count == 0)  t_out();
  y_out(a);
  ++ m_count;
  if (m_count == m_period) {
    if (! m_preceed)  t_out();
    m_count = 0;
  }
}
